package project

import (
	"context"
	"github.com/gogf/gf/v2/os/gtime"
	"time"
	v1 "wh-1-backend/api/v1"
	"wh-1-backend/internal/dao"
	"wh-1-backend/internal/model"
	"wh-1-backend/internal/model/do"
	"wh-1-backend/internal/model/entity"
	"wh-1-backend/internal/service"
)

type sProject struct{}

func New() *sProject {
	return &sProject{}
}

func init() {
	service.RegisterProject(New())
}

func (p *sProject) ListByConditionWithPage(ctx context.Context, pageInput model.PageInput, conInput model.ProjectPageListConditionInput) (total int, list []*model.SimpleProjectList, err error) {
	m := dao.Project.Ctx(ctx)
	if conInput.Title != "" {
		m.WhereLike(dao.Project.Columns().Title, conInput.Title+"%")
	}
	total, err = m.Count()
	if err != nil || total == 0 {
		return
	}
	err = m.OrderDesc(dao.Project.Columns().Id).Page(pageInput.Page, pageInput.PageSize).Scan(&list)
	if err != nil {
		return
	}
	//
	var cityIds []uint
	var companyIds []uint
	var projectIds []uint
	for _, re := range list {
		cityIds = append(cityIds, re.CityId)
		companyIds = append(companyIds, re.CompanyId)
		projectIds = append(projectIds, re.Id)
	}
	cities, err := service.City().ListByIds(ctx, cityIds)
	if err != nil {
		return
	}
	var cityKeyList = make(map[uint]*model.CityList)
	for _, city := range cities {
		cityKeyList[city.Id] = city
	}
	companyLists, err := service.Company().ListByIds(ctx, companyIds)
	if err != nil {
		return
	}
	var companyKeyList = make(map[uint]*v1.SimpleCompanyList)
	for _, company := range companyLists {
		companyKeyList[company.Id] = company
	}
	var projectResumeList []*entity.ProjectResume
	err = dao.ProjectResume.Ctx(ctx).WhereIn(dao.ProjectResume.Columns().ProjectId, projectIds).Scan(&projectResumeList)
	if err != nil {
		projectResumeList = make([]*entity.ProjectResume, 0)
	}
	var projectResumeKeyList = make(map[uint][]uint)
	for _, re := range projectResumeList {
		projectResumeKeyList[re.ProjectId] = append(projectResumeKeyList[re.ProjectId], re.ResumeId)
	}
	for _, re := range list {
		if city, ok := cityKeyList[re.CityId]; ok {
			re.City = city
		}
		if company, ok := companyKeyList[re.CompanyId]; ok {
			re.Company = company
		}
		if pResume, ok := projectResumeKeyList[re.Id]; ok {
			re.ResumeIds = pResume
		} else {
			re.ResumeIds = []uint{}
		}
	}
	return
}

func (p *sProject) Save(ctx context.Context, input model.EditProjectInput) (id uint, err error) {
	lastInsertId, err := dao.Project.Ctx(ctx).InsertAndGetId(do.Project{
		CompanyId:              input.CompanyId,
		Contact:                input.Contact,
		Title:                  input.Title,
		IndustryId:             input.IndustryId,
		FunctionId:             input.FunctionId,
		CityId:                 input.CityId,
		Address:                input.Address,
		StatusId:               input.StatusId,
		StartAt:                input.StartAt,
		EndAt:                  input.EndAt,
		EnterpriseBackgroundId: input.EnterpriseBackgroundId,
		NationalityId:          input.NationalityId,
		EducationBackgroundId:  input.EducationBackgroundId,
		MaxAge:                 input.MaxAge,
		MinAge:                 input.MinAge,
		MaxWorkAge:             input.MaxWorkAge,
		MinWorkAge:             input.MinWorkAge,
		MaxSalary:              input.MaxSalary,
		MinSalary:              input.MinSalary,
		Gender:                 input.Gender,
		RecruitReason:          input.RecruitReason,
		InsideOpenAt:           input.InsideOpenAt,
		DptStatus:              input.DptStatus,
		ReportFor:              input.ReportFor,
		IsSole:                 input.IsSole,
		IsAdd:                  input.IsAdd,
		IsSecrecy:              input.IsSecrecy,
		CoreProblem:            input.CoreProblem,
		JobStyle:               input.JobStyle,
		HardRequirement:        input.HardRequirement,
		Precedence:             input.Precedence,
		SalaryModel:            input.SalaryModel,
		JobDes:                 input.JobDes,
		JobSuperiority:         input.JobSuperiority,
		InterviewModel:         input.InterviewModel,
		Direction:              input.Direction,
		PresentSituation:       input.PresentSituation,
		Target:                 input.Target,
	})
	return uint(lastInsertId), err
}

func (p *sProject) Update(ctx context.Context, id uint, input model.EditProjectInput) (err error) {
	_, err = dao.Project.Ctx(ctx).Where(dao.Project.Columns().Id, id).Update(do.Project{
		CompanyId:              input.CompanyId,
		Contact:                input.Contact,
		Title:                  input.Title,
		IndustryId:             input.IndustryId,
		FunctionId:             input.FunctionId,
		CityId:                 input.CityId,
		Address:                input.Address,
		StatusId:               input.StatusId,
		StartAt:                input.StartAt,
		EndAt:                  input.EndAt,
		EnterpriseBackgroundId: input.EnterpriseBackgroundId,
		NationalityId:          input.NationalityId,
		EducationBackgroundId:  input.EducationBackgroundId,
		MaxAge:                 input.MaxAge,
		MinAge:                 input.MinAge,
		MaxWorkAge:             input.MaxWorkAge,
		MinWorkAge:             input.MinWorkAge,
		MaxSalary:              input.MaxSalary,
		MinSalary:              input.MinSalary,
		Gender:                 input.Gender,
		RecruitReason:          input.RecruitReason,
		InsideOpenAt:           input.InsideOpenAt,
		DptStatus:              input.DptStatus,
		ReportFor:              input.ReportFor,
		IsSole:                 input.IsSole,
		IsAdd:                  input.IsAdd,
		IsSecrecy:              input.IsSecrecy,
		CoreProblem:            input.CoreProblem,
		JobStyle:               input.JobStyle,
		HardRequirement:        input.HardRequirement,
		Precedence:             input.Precedence,
		SalaryModel:            input.SalaryModel,
		JobDes:                 input.JobDes,
		JobSuperiority:         input.JobSuperiority,
		InterviewModel:         input.InterviewModel,
		Direction:              input.Direction,
		PresentSituation:       input.PresentSituation,
		Target:                 input.Target,
	})
	return
}

func (p *sProject) GetById(ctx context.Context, id uint) (res *entity.Project, err error) {
	err = dao.Project.Ctx(ctx).Where(dao.Project.Columns().Id, id).Scan(&res)
	return
}

func (p *sProject) SoftDelete(ctx context.Context, ids []uint) (err error) {
	_, err = dao.Project.Ctx(ctx).WhereIn(dao.Project.Columns().Id, ids).Update(do.Project{DeletedAt: gtime.New(time.Now())})
	return
}

func (p *sProject) AttachResume(ctx context.Context, projectId uint, ids []uint) (err error) {
	list := make([]*do.ProjectResume, 0, 8)
	for _, id := range ids {
		list = append(list, &do.ProjectResume{ProjectId: projectId, ResumeId: id})
	}
	_, err = dao.ProjectResume.Ctx(ctx).Insert(list)
	return
}

func (p *sProject) UnAttachResume(ctx context.Context, projectId uint, id uint) (err error) {
	_, err = dao.ProjectResume.Ctx(ctx).Where(dao.ProjectResume.Columns().ProjectId, projectId).Where(dao.ProjectResume.Columns().ResumeId, id).Delete()
	return
}

func (p *sProject) ProjectResumeListByConditionWithPage(ctx context.Context, projectId uint, pageInput model.PageInput, conInput model.ResumePageListCondition) (total int, list []*model.ProjectResumeList, err error) {
	m := dao.ProjectResume.
		Ctx(ctx).
		LeftJoin(dao.Resume.Table(), "project_resume.resume_id=resume.id").
		WherePrefix(dao.ProjectResume.Table(), do.ProjectResume{ProjectId: projectId})

	if conInput.Username != "" {
		m = m.WherePrefixLike(dao.Resume.Table(), dao.Resume.Columns().Username, conInput.Username+"%")
	}
	if conInput.Phone != "" {
		m = m.WherePrefixLike(dao.Resume.Table(), dao.Resume.Columns().Phone, conInput.Phone+"%")
	}
	total, err = m.Count()
	if err != nil || total == 0 {
		return
	}
	err = m.
		FieldsPrefix(dao.Resume.Table(), "*").
		OrderDesc(dao.ProjectResume.Columns().Id).
		Page(pageInput.Page, pageInput.PageSize).
		Scan(&list)
	return
}
